#
# VO MAKER
#

class Maker:
    def __init__(self,cls,out):
        self.cls=cls
        self.out=out
    def go(self):
        self.fp = self.open()
        # gogogo
        self.package_begin()
        self.class_begin()
        # field declare
        for fd in self.cls['fields']:
            self.field_declare(fd)
        # constructor
        self.constructor()
        # pack , unpack
        self.define_pack()
        self.define_unpack()
        self.class_end()
        self.package_end()
        self.fp.close()        
    def p(self, *m,end='\n'):
        print(*m, file=self.fp, end=end)
        #print(*m, end=end)

class JavaMaker(Maker):
    def __init__(self,cls,out):
        super().__init__(cls,out)
        # 定义的类型
        self.td={
            'short':'short',
            'int':'int',
            'long':'long',
            'float':'float',
            'double':'double',
            'String':'String',
        }
        # 读写bytearray的时候的类型, 保证兼容即可
        # 这个需要和客户端一致的
        self.td2 = {
            'short':'Short',
            'int':'Int',
            'long':'Long',
            'float':'Float',
            'double':'Double',
            'String':'UTF',
        }
        
    def open(self):
        return open(self.out + self.cls['name'] + '.java', 'w', 300, 'utf-8')
    def package_begin(self):
        self.p('package {0};'.format(self.cls['package']))
        self.p('import flash.utils.ByteArray;')
        self.p('import java.io.IOException;')
    def package_end(self):
        pass
    def class_begin(self):
        if 'extends' in self.cls:
            self.p('public class {0} extends {1} {{'.format(
                self.cls['name'], self.cls['extends']))
        else:
            self.p('public class {0} implements Cloneable {{'.format(self.cls['name']))
            self.p("""@Override
public Object clone() throws CloneNotSupportedException {
	return super.clone();
}""")
    def class_end(self):
        self.p('}')
    def field_declare(self,fd):
        t = fd['type']
        if len(t) > 2 and t[-2:] == '[]':
            self.p('public {1} {0};'.format(fd['name'], self.td.get(t, t)))
        else:
            self.p('public {1} {0};'.format(fd['name'], self.td.get(t, t)))
    def define_pack(self):
        if 'extends' in self.cls:
            self.p('@Override', end=' ')
        self.p('public void pack(ByteArray b) throws IOException {')
        if 'extends' in self.cls:
            self.p('super.pack(b);')
        for fd in self.cls['fields']:
            t = fd['type']
            if len(t) > 2 and t[-2:] == '[]':
                t = t[:-2]
                t = self.td.get(t,t)
                name = fd['name']
                self.p('b.writeShort({0}.length);'.format(name))
                self.p('for(int i = 0; i < {0}.length; i++) {{'.format(name))
                if t in self.td:
                    pre = self.td2[t]
                    self.p('b.write{1}(this.{0}[i]);'.format(name, pre))
                else:
                    self.p('this.{0}[i].pack(b);'.format(name))
                self.p('}')
            else:
                if t in self.td:
                    pre = self.td2[t]
                    self.p('b.write{1}(this.{0});'.format(fd['name'], pre))
                else:
                    self.p('this.{0}.pack(b);'.format(fd['name']))
        self.p('}')
    def define_unpack(self):
        if 'extends' in self.cls:
            self.p('@Override', end=' ')
        self.p('public void unpack(ByteArray b) throws IOException {')
        if 'extends' in self.cls:
            self.p('super.unpack(b);')
        for fd in self.cls['fields']:
            t = fd['type']
            if len(t) > 2 and t[-2:] == '[]':
                t = t[:-2]
                t = self.td.get(t,t)
                name = fd['name']
                iname = '_i' + name
                self.p('int {0} = b.readShort();'.format(iname))
                self.p('this.{0} = new {1}[{2}];'.format(name, t, iname))
                self.p('for(int i = 0; i < {0}; i++) {{'.format(iname))
                if t in self.td:
                    pre = self.td2[t]
                    self.p('this.{0}[i] = b.read{1}();'.format(name, pre))
                else:
                    self.p('this.{0}[i].unpack(b);'.format(name))
                self.p('}')
            else:
                if t in self.td:
                    pre = self.td2[t]
                    self.p('this.{0} = b.read{1}();'.format(fd['name'], pre))
                else:
                    self.p('this.{0} = new {1}();'.format(fd['name'], t))
                    self.p('this.{0}.unpack(b);'.format(fd['name']))
        self.p('}')
    def constructor(self):
        if 'extends' in self.cls:
            self.p('@Override')
        self.p('public int getVid() {{ return {0}; }}'.format(self.cls['vid']))

class As3Maker(Maker):
    def __init__(self,cls,out):
        super().__init__(cls,out)
        # 定义的类型
        self.td = {
            'short':'int',
            'int':'int',
            'long':'Number',
            'float':'Number',
            'double':'Number',
            'String':'String',          
        }
        # 读写bytearray的时候的类型, 保证兼容即可
        self.td2 = {
            'short':'Short',
            'int':'Int',
            'long':'Long',
            'float':'Float',
            'double':'Double',
            'String':'UTF',
        }
    def open(self):
        return open(self.out + self.cls['name'] + '.as', 'w', 300, 'utf-8')
    def package_begin(self):
        self.p('package {0} {{'.format(self.cls['package']))
        self.p('import flash.utils.ByteArray;')
    def package_end(self):
        self.p('}')
    def class_begin(self):
        if 'extends' in self.cls:
            self.p('public class {0} extends {1} {{'.format(
                self.cls['name'], self.cls['extends']))
        else:
            self.p('public class {0} {{'.format(self.cls['name']))
    def class_end(self):
        self.p('}')
    def field_declare(self,fd):
        t = fd['type']
        if len(t) > 2 and t[-2:] == '[]':
            t = t[:-2]
            self.p('public var {0}: Vector.<{1}>;'.format(fd['name'], self.td.get(t, t)))
        else:
            self.p('public var {0}: {1};'.format(fd['name'], self.td.get(t, t)))
    def define_pack(self):
        if 'extends' in self.cls:
            self.p('override', end=' ')
        self.p('public function pack(b:ByteArray):void {')
        if 'extends' in self.cls:
            self.p('super.pack(b);')
        for fd in self.cls['fields']:
            t = fd['type']
            name = fd['name']
            if len(t) > 2 and t[-2:] == '[]':
                t = t[:-2]
                t = self.td.get(t,t)
                self.p('b.writeShort({0}.length);'.format(name))
                self.p('for(var _i{0}:int = 0; _i{0} < {0}.length; _i{0}++) {{'.format(name))
                if t in self.td:
                    pre = self.td2[t]
                    self.p('b.write{1}(this.{0}[_i{0}]);'.format(name, pre))
                else:
                    self.p('this.{0}[_i{0}].pack(b);'.format(name))
                self.p('}')
            else:
                if t in self.td:
                    pre = self.td2[t]
                    self.p('b.write{1}(this.{0});'.format(name, pre))
                else:
                    self.p('this.{0}.pack(b);'.format(name))
        self.p('}')
    def define_unpack(self):
        if 'extends' in self.cls:
            self.p('override', end=' ')
        self.p('public function unpack(b:ByteArray):void {')
        if 'extends' in self.cls:
            self.p('super.unpack(b);')
        for fd in self.cls['fields']:
            t = fd['type']
            name = fd['name']
            if len(t) > 2 and t[-2:] == '[]':
                t = t[:-2]
                t = self.td.get(t,t)
                self.p('this.{0} = new Vector.<{1}>();'.format(name, t))
                self.p('var n{0}:int = b.readShort();'.format(name))
                self.p('for(var _i{0}:int=0;_i{0}<n{0};_i{0}++) {{'.format(name))
                if t in self.td:
                    pre = self.td2[t]
                    self.p('this.{0}.push(b.read{1}());'.format(name, pre))
                else:
                    self.p('var _it:{0} = new {0}();_it.unpack(b);this.{0}.push(_it);'.format(t))
                self.p('}')
            else:
                if t in self.td:
                    pre = self.td2[t]
                    self.p('this.{0} = b.read{1}();'.format(name, pre))
                else:
                    self.p('this.{0} = new {1}();'.format(name, t))
                    self.p('this.{0}.unpack(b);'.format(name))
        self.p('}')
    def constructor(self):
        if 'extends' in self.cls:
            self.p('override', end=' ')
        self.p('public function get vid():int {{ return {0}; }}'.format(self.cls['vid']))

